package com.yjz.jvm.juc.ExecutorService.future;

import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import com.yjz.jvm.juc.ExecutorService.BizExecutorsUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;


import static java.lang.Thread.sleep;

public class CompletableFutureTest {

    @Test
    public void 测试CompletableFuture() {
        //订购航班
        CompletableFuture airPlane = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询航班");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("订购航班");
            return "航班信息";
        }, BizExecutorsUtils.EXECUTOR);

        //订购酒店
        CompletableFuture hotel = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询酒店");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("订购酒店");
            return "酒店信息";
        }, BizExecutorsUtils.EXECUTOR);

        //订购租车服务

        CompletableFuture tax = hotel.thenCombine(airPlane, (fly, room) -> {
            System.out.println("根据航班+酒店，订购租车服务");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "目前信息："+fly+":"+room+"，租车信息";
        });

        // 接下来两句话应该同时打印出来，因为本质上都是在等待CompletableFuture完成

        tax.whenComplete((x,y)->{
            System.out.println("处理结束，返回值"+x+""+y);
        });

        System.out.println(tax.join());

    }

    @Test
    public void 测试任务集合() throws ExecutionException, InterruptedException {
        CompletableFuture<String> result = CompletableFuture.supplyAsync(() -> {
            try {
                sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("第一个任务");
            return "hello1";
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            System.out.println("第二个任务");
            try {
                sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello2";
        }), (t, u) -> {
            System.out.println("lambda整合2个结果");
            return t + " " + u;
        });
        System.out.println(result.get());
    }


    @Test
    public void 测试合并多个微服务的查询结果() throws ExecutionException, InterruptedException {
        final Stopwatch stopwatch = Stopwatch.createStarted();

        CompletableFuture<String> result = CompletableFuture.supplyAsync(() -> {
            try {
                // 这里模拟微服务A的查询接口
                System.out.println("A======" + Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return RandomStringUtils.randomAlphabetic(10);
        }).thenCombineAsync(
                CompletableFuture.supplyAsync(() -> {
                    try {
                        // 这里模拟微服务B的查询接口
                        System.out.println("completablefutureB======" + Thread.currentThread().getName());
                        TimeUnit.SECONDS.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return RandomStringUtils.randomAlphabetic(20);
                })
                , (r1, r2) -> {
                    // 合并两个查询结果
                    return r1 + " = " + r2;
                });


        System.out.println("main======" + Thread.currentThread().getName());
        System.out.println(result.get());
        stopwatch.stop();
        // 整体请求时间以最长的来定
        System.out.println("senconds:" + stopwatch.elapsed(TimeUnit.SECONDS));
    }



    @Test
    public void 测试设置默认值() throws ExecutionException, InterruptedException {
        // 创建一个CompletableFuture对象
        CompletableFuture<String> future =  CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "航班信息";
        }, BizExecutorsUtils.EXECUTOR);

        // 设置一个时间，等待future完成
        try {
            Thread.sleep(7000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /**
         *  如果future已经完成了，则默认值设置失败
         *
         *  如果还没完成，则设置默认值成功，则后续调用 get、join方法都会返回 这个默认值
         */
        boolean triggered = future.complete("Hello, World!");

        // 输出设置返回值是否成功
        System.out.println("Complete triggered: " + triggered);


        // 获取CompletableFuture对象的返回值（可能返回默认值哦）
        System.out.println("Result by join: " + future.join());
        System.out.println("Result by get: " + future.get());
    }
}
